import 'dart:io';

import 'package:connectivity/connectivity.dart';
import 'package:dio/dio.dart';
import 'package:play_android/com/zhihaoliang/const/AppApi.dart';
import 'package:play_android/com/zhihaoliang/const/AppStr.dart';
import 'package:play_android/com/zhihaoliang/const/Appkey.dart';
import 'package:play_android/com/zhihaoliang/const/Config.dart';
import 'package:play_android/com/zhihaoliang/http/ResultData.dart';
import 'package:play_android/com/zhihaoliang/http/HttpException.dart';
import 'package:play_android/com/zhihaoliang/util/SpUtil.dart';

///  ***************************************************************************
///  网路请求的工具类
///  ***************************************************************************

class HttpRequest {
  static final HttpRequest _httpRequest = HttpRequest._internal();

  static const COOKIE = "Cookie";

  Map<String, String> _cookie;

  Dio _dio;

  factory HttpRequest() {
    return _httpRequest;
  }

  _initDio() {
// 或者通过传递一个 `BaseOptions`来创建dio实例
    BaseOptions options = new BaseOptions(
      connectTimeout: 5000,
      receiveTimeout: 3000,
    );
    _dio = new Dio(options);

    if (Config.DEBUG) {
      _dio.interceptors
          .add(InterceptorsWrapper(onRequest: (RequestOptions options) {
        print("\n================== 请求数据 ==========================");
        print("url = ${options.uri.toString()}");
        print("headers = ${options.headers}");
        print("params = ${options.data}");
      }, onResponse: (Response response) {
        print("\n================== 响应数据 ==========================");
        print("code = ${response.statusCode}");
        print("data = ${response.data}");
        print("\n");
      }, onError: (DioError e) {
        print("\n================== 错误响应数据 ======================");
        print("type = ${e.type}");
        print("message = ${e.message}");
        print("stackTrace = ${e.stackTrace}");
        print("\n");
      }));
    }
  }

  HttpRequest._internal() {
    _initDio();
  }

  Map optionParams = {
    "timeoutMs": 15000,
    "token": null,
    "authorizationCode": null,
  };

  get(String url, [Map param]) async {
    return await _request(
        _getCompaleteUrl(url), param, null, new Options(method: "GET"));
  }

  post(String url, [Map param]) async {
    return await _request(
        _getCompaleteUrl(url), param, null, new Options(method: 'POST'));
  }

  delete(String url, [Map param]) async {
    return await _request(
        _getCompaleteUrl(url), param, null, new Options(method: 'DELETE'));
  }

  put(String url, [Map param]) async {
    return await _request(_getCompaleteUrl(url), param, null,
        new Options(method: "PUT", contentType: ContentType.text));
  }

  static String _getCompaleteUrl(String url) {
    if (url.startsWith("http") || url.startsWith("https")) {
      return url;
    }

    return AppApi.BASEURL + url;
  }

  _request(url, params, Map<String, String> header, Options option) async {
    var connectivityResult = await (new Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      throw HttpException(AppStr.NETWORK_ERROR, url);
    }

    if (_dio.options.headers != null) {
      _cookie = await getCookie();
      if (_cookie[COOKIE] != null) {
        _dio.options.headers.addAll(_cookie);
      } else {
        _dio.options.headers.clear();
      }
    }

    Response<Map<String, dynamic>> response;
    try {
      response =
          await _dio.request(url, queryParameters: params, options: option);
    } on DioError catch (e) {
      // 请求错误处理
      throw HttpException(e.message, url);
    }

    try {
      if (option.contentType != null &&
          option.contentType.primaryType == "text") {
        return await _initResut(response, url);
      }

      if (response.statusCode == 200 || response.statusCode == 201) {
        return await _initResut(response, url);
      }
    } catch (e) {
      throw HttpException(e.message, url);
    }

    throw HttpException(AppStr.UNKOWN_EXCEPTION, url);
  }

  Future<ResultData> _initResut(
      Response<Map<String, dynamic>> response, String url) async {
    if (url.endsWith(AppApi.LOGIN)) {
      StringBuffer stringBuffer = new StringBuffer();
      response.headers['set-cookie'].forEach((item) {
        stringBuffer.write(item);
      });
      setCookie(stringBuffer.toString());
    }
    ResultData resultData = new ResultData(response.data, url,
        response.data["errorCode"], response.data["errorMsg"]);
    return resultData;
  }

  Future<Map<String, String>> getCookie() async {
    if (_cookie == null) {
      String cookieValue = await new SpUtil().getString(AppKey.COOKIE);
      if (cookieValue == null) {
        _cookie = Map();
      } else {
        _cookie = {COOKIE: cookieValue};
      }
      return _cookie;
    }
    return _cookie;
  }

  void setCookie(String cookieValue) async {
    if (cookieValue == null) {
      return;
    }

    await new SpUtil().saveByKey(AppKey.COOKIE, cookieValue);
    if (_cookie == null) {
      _cookie = Map();
    }
    _cookie[COOKIE] = cookieValue;
  }

  Future<bool> isCookie() async {
    if (_cookie == null || !_cookie.containsKey("Cookie")) {
      return await new SpUtil().getString(AppKey.COOKIE) != null;
    }

    return true;
  }

  Future clearCookie() async {
    _cookie = Map();
    if (_dio.options.headers != null) {
      _dio.options.headers.clear();
    }

    SpUtil().removeByKey(AppKey.COOKIE);
  }
}
